import { RVOMath, Vector2 } from "./rvo2/Common";
import { Simulator } from "./rvo2/Simulator";

export default class GameMgr2 {
	agentCnt = 10;
	space = 15;
	speed = 1;
	goals: Vector2[] = [];
	mSpheres: Laya.Sprite[] = [];

	constructor() {
		this.start();
		this.onEnable();
		Laya.timer.frameLoop(1, this, this.update);
	}

	onEnable() {
		Laya.stage.on(Laya.Event.MOUSE_DOWN, this, this.onMouseDown);
		Laya.stage.on(Laya.Event.MOUSE_UP, this, this.onMouseUp);
		Laya.stage.on(Laya.Event.MOUSE_WHEEL, this, this.onMouseWheel);
	}

	onDisable() {
		Laya.stage.off(Laya.Event.MOUSE_DOWN, this, this.onMouseDown);
		Laya.stage.off(Laya.Event.MOUSE_UP, this, this.onMouseUp);
	}

	start() {
		let simulator = Simulator.instance;
		this.addObstacle();
		simulator.processObstacles();

		simulator.setAgentDefaults(5, 4, 1, 0.1, 5, this.speed, new Vector2(0, 0));
		this.createAgent(new Vector2(10, 10), "blue", 1, 5);
		this.createAgent(new Vector2(500, 10), "red", 1, 10);
		this.createGameObject(new Vector2(300, 400), "yellow", 100000, 50);
	}

	addObstacle() {
		let simulator = Simulator.instance;
		let obstacle1: Vector2[] = [];
		obstacle1.push(new Vector2(-10.0, 40.0));
		obstacle1.push(new Vector2(-80.0, 40.0));
		obstacle1.push(new Vector2(-80.0, 10.0));
		obstacle1.push(new Vector2(-10.0, 10.0));
		simulator.addObstacle(obstacle1);

		let sp1 = new Laya.Sprite();
		sp1.graphics.drawPoly(
			300,
			300,
			[-10.0, 40.0, -80.0, 40.0, -80.0, 10.0, -10.0, 10.0],
			"#FF7F50"
		);
		Laya.stage.addChild(sp1);

		let obstacle2: Vector2[] = [];
		obstacle2.push(new Vector2(50.0, 60.0));
		obstacle2.push(new Vector2(30.0, 30.0));
		obstacle2.push(new Vector2(50.0, -10.0));
		obstacle2.push(new Vector2(80.0, 20.0));
		obstacle2.push(new Vector2(70.0, 60.0));
		simulator.addObstacle(obstacle2);

		let sp2 = new Laya.Sprite();
		sp2.graphics.drawPoly(
			0,
			0,
			[50.0, 60.0, 30.0, 30.0, 50.0, -10.0, 80.0, 20.0, 70.0, 60.0],
			"#FF7F50"
		);
		Laya.stage.addChild(sp2);
	}

	onMouseDown(event: Event) {
		let index = 0;
		let x = Laya.stage.mouseX;
		let y = Laya.stage.mouseY;
		for (let i = 0; i < this.agentCnt; i++) {
			// let j = 0;
			for (let j = 0; j < this.agentCnt; j++) {
				let p = this.goals[index++];
				p.x = i * this.space + x;
				p.y = j * this.space + y;
			}
		}
	}

	onMouseUp(event: Event) {
		let x = Laya.stage.mouseX;
		let y = Laya.stage.mouseY;
		let index = this.agentCnt * this.agentCnt;
		for (let i = 0; i < this.agentCnt; i++) {
			for (let j = 0; j < this.agentCnt; j++) {
				let p = this.goals[index++];
				p.x = i * this.space + x;
				p.y = j * this.space + y;
			}
		}
	}

	onMouseWheel(event: Event) {
		let x = Laya.stage.mouseX;
		let y = Laya.stage.mouseY;
		let index = this.agentCnt * this.agentCnt * 2;
		let p = this.goals[index++];
		p.x = x;
		p.y = y;
	}

	createAgent(pos: Vector2, fillColor: any, mass: number, radius: number) {
		let cnt = this.agentCnt;
		for (let i = 0; i < cnt; i++) {
			// let j = 0;
			for (let j = 0; j < cnt; j++) {
				let p = new Vector2(
					i * this.space + pos.x + radius * i,
					j * this.space + pos.y + radius * j
				);
				this.createGameObject(p, fillColor, mass, radius);
			}
		}
	}

	createGameObject(
		position: Vector2,
		fillColor: any,
		mass: number,
		radius: number
	) {
		let simulator = Simulator.instance;
		let idx = simulator.addAgent(position, radius);
		simulator.setAgentMass(idx, mass);
		this.goals.push(position);
		let node = new Laya.Sprite();
		node.graphics.drawCircle(0, 0, radius, fillColor);
		this.mSpheres.push(node);
		node.pos(position.x, position.y);
		Laya.stage.addChild(node);
	}

	setPreferredVelocities() {
		let agentCnt = Simulator.instance.getNumAgents();
		for (let i = 0; i < agentCnt; i++) {
			let agentPos = Simulator.instance.getAgentPosition(i);

			let goalVector = this.goals[i].minus(agentPos);
			let disSqr = RVOMath.absSq(goalVector);
			if (i == 0) {
				console.log(this.goals[i], agentPos, disSqr);
			}
			// stop
			if (disSqr < RVOMath.RVO_EPSILON) {
				// Agent is within one radius of its goal, set preferred velocity to zero
				Simulator.instance.setAgentPrefVelocity(i, new Vector2(0.0, 0.0));
				continue;
			}
			if (disSqr > 1.0) {
				goalVector = RVOMath.normalize(goalVector).scale(this.speed);
			} else {
				goalVector = RVOMath.normalize(goalVector).scale(this.speed * 0.01);
			}
			Simulator.instance.setAgentPrefVelocity(i, goalVector.scale(0.1));
			// let angle = Math.random() * 2.0 * Math.PI;
			// let dist = Math.random() * 0.0001;
			// Simulator.instance.setAgentPrefVelocity(
			// 	i,
			// 	agentPos.plus(
			// 		new Vector2(Math.cos(angle), Math.sin(angle)).scale(dist)
			// 	)
			// );
		}
	}

	update() {
		let dt = Laya.timer.delta;
		dt = Math.min(dt, 33);
		// 更新逻辑坐标
		this.setPreferredVelocities();
		Simulator.instance.run(dt);

		// 更新渲染坐标
		for (let i = 0; i < Simulator.instance.getNumAgents(); i++) {
			let p = Simulator.instance.getAgentPosition(i);
			this.mSpheres[i].pos(p.x, p.y);
		}
	}
}
